package com.imay.photopicker.manager;

import android.animation.Animator;
import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.content.Context;
import android.graphics.Rect;
import android.hardware.Camera;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.ScaleGestureDetector;
import android.view.View;
import android.widget.ImageView;
import android.widget.RelativeLayout;

import com.imay.capturefilter.camera.CameraEngine;
import com.imay.capturefilter.widget.MagicCameraView;

import java.util.ArrayList;
import java.util.List;

/**
 * Created by Administrator on 2017/3/18.
 */

public class CameraManager {
    private final ScaleGestureDetector mScaleGestureDetector;
    private final GestureDetector mGestureDetetor;
    private final ImageView mIvFocus;
    private int surfaceWidth;
    private int surfaceHeight;

    private State state;
    private int mFocusX = 0, mFocusY = 0;

    private enum State {NONE, DRAG, ZOOM, FLING, ANIMATE_ZOOM}


    public CameraManager(Context context, final MagicCameraView mMagicCameraView, ImageView mIvFocus){
        mScaleGestureDetector = new ScaleGestureDetector(context, new ScaleGestureListener());
        mGestureDetetor = new GestureDetector(context, new GestureDetetor());
        surfaceWidth = mMagicCameraView.getSurfaceWidth();
        surfaceHeight = mMagicCameraView.getSurfaceHeight();
        this.mIvFocus = mIvFocus;
        mMagicCameraView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View view, MotionEvent event) {
                surfaceWidth = mMagicCameraView.getSurfaceWidth();
                surfaceHeight = mMagicCameraView.getSurfaceHeight();
                if (event.getPointerCount() == 1) {
                    mGestureDetetor.onTouchEvent(event);
                } else {
                    mScaleGestureDetector.onTouchEvent(event);
                }
                return true;
            }
        });
    }

    public void setState(State state) {
        this.state = state;
    }

    /**
     * 缩放监听
     */
    public class ScaleGestureListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
        private float scale = 0;

        @Override
        public boolean onScale(ScaleGestureDetector detector) {
            if (detector.getScaleFactor() > 1)//放大
                scale = 1;
            else
                scale = -2;
            CameraEngine.setZoom(scale);
            return true;
        }

        @Override
        public boolean onScaleBegin(ScaleGestureDetector detector) {
            setState(State.ZOOM);
            return true;    // 一定要返回true才会进入onScale()这个函数
        }

        @Override
        public void onScaleEnd(ScaleGestureDetector detector) {
            setState(State.NONE);
        }
    }

    /**
     * 监听拖拽滑动
     */
    public class GestureDetetor extends GestureDetector.SimpleOnGestureListener {

        private static final int FLING_MIN_DISTANCE = 100;
        private static final int FLING_MIN_VELOCITY = 0;

        @Override
        public boolean onDown(MotionEvent motionEvent) {
            setState(State.DRAG);
            return false;
        }

        @Override
        public boolean onSingleTapConfirmed(MotionEvent event) {
            if (state == State.DRAG) {
                //Log.i(TAG,event.getX()+"-----"+event.getY());
                //Log.i(TAG,event.getRawX()+"-----"+event.getRawY());
                mFocusX = (int) event.getX();
                mFocusY = (int) event.getY();
                handleFocusMetering(event);    //自动对焦
            }
            setState(State.NONE);
            return super.onSingleTapConfirmed(event);
        }

        @Override
        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
            return true;
        }
    }

    private void handleFocusMetering(final MotionEvent event) {
        Camera mCamera = CameraEngine.getCamera();
        if(mCamera != null){
            Rect focusRect = calculateTapArea(event.getX(), event.getY(), 1f);
            Rect meteringRect = calculateTapArea(event.getX(), event.getY(), 1.5f);
            Camera.Parameters parameters = mCamera.getParameters();
            parameters.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);

            if (parameters.getMaxNumFocusAreas() > 0) {
                List<Camera.Area> focusAreas = new ArrayList<Camera.Area>();
                focusAreas.add(new Camera.Area(focusRect, 1000));
                parameters.setFocusAreas(focusAreas);
            }

            if (parameters.getMaxNumMeteringAreas() > 0) {
                List<Camera.Area> meteringAreas = new ArrayList<Camera.Area>();
                meteringAreas.add(new Camera.Area(meteringRect, 1000));
                parameters.setMeteringAreas(meteringAreas);
            }

            try{
                mCamera.setParameters(parameters);
                updateFocusUI();
                mCamera.autoFocus(new Camera.AutoFocusCallback() {
                    @Override
                    public void onAutoFocus(boolean b, Camera camera) {

                    }
                });
            }catch (Exception e){
                e.printStackTrace();
            }
        }
    }

    private Rect calculateTapArea(float x, float y, float coefficient) {
        float focusAreaSize = 100;
        int areaSize = Float.valueOf(focusAreaSize * coefficient).intValue();

        // 获取屏幕中点
        int centerScreenX = surfaceWidth / 2;
        int centerScreenY = surfaceHeight / 2;

        // 计算以屏幕的中点的触点坐标
        int centerScreenTouchX = (int) (x - centerScreenX);
        int centerScreenTouchY = (int) (y - centerScreenY);

        // 以相机对焦为X(-1000,1000),Y(-1000,1000)的二维坐标中按比例计算对焦的坐标
        int centerX = (centerScreenTouchX * 1000)/centerScreenX;
        int centerY = (centerScreenTouchY * 1000)/centerScreenY;

        int left = clamp(centerX - areaSize / 2, -1000, 1000);
        int right = clamp(centerX + areaSize /2 , -1000, 1000);
        int top = clamp(centerY - areaSize / 2, -1000, 1000);
        int bottom = clamp(centerY + areaSize /2 , -1000, 1000);
        return new Rect(left, top, right, bottom);
    }

    private int clamp(int x, int min, int max) {
        if (x > max) {
            return max;
        }
        if (x < min) {
            return min;
        }
        return x;
    }

    private void updateFocusUI() {
        RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) mIvFocus.getLayoutParams();
        params.setMargins(mFocusX - 50, mFocusY - 50, 0, 0);
        mIvFocus.setLayoutParams(params);
        mIvFocus.setVisibility(ImageView.VISIBLE);
        // 属性动画
        AnimatorSet set = new AnimatorSet();
        ObjectAnimator oaX = ObjectAnimator.ofFloat(mIvFocus, "scaleX", 1.0f, 1.1f);
        ObjectAnimator oaY = ObjectAnimator.ofFloat(mIvFocus, "scaleY", 1.0f, 1.1f);
        ObjectAnimator oaX2 = ObjectAnimator.ofFloat(mIvFocus, "scaleX", 1.1f, 0.9f);
        ObjectAnimator oaY2 = ObjectAnimator.ofFloat(mIvFocus, "scaleY", 1.1f, 0.9f);
        ObjectAnimator oaX3 = ObjectAnimator.ofFloat(mIvFocus, "scaleX", 0.9f, 1.0f);
        ObjectAnimator oaY3 = ObjectAnimator.ofFloat(mIvFocus, "scaleY", 0.9f, 1.0f);
        set.play(oaX).with(oaY);
        set.play(oaX).before(oaX2).before(oaY2);
        set.play(oaX2).before(oaX3).before(oaY3);
        set.setDuration(300);
        set.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animator) {

            }

            @Override
            public void onAnimationEnd(Animator animator) {
                mIvFocus.setVisibility(View.GONE);
            }

            @Override
            public void onAnimationCancel(Animator animator) {

            }

            @Override
            public void onAnimationRepeat(Animator animator) {

            }
        });
        set.start();
    }
}
